package adventure.commands;

import adventure.*;
import player.*;
import colour.ColourUtil;

import java.util.ArrayList;

/**
 *
 * @author Michael Hanns
 *
 */
public class Run extends AbstractCommand {

    public Run(Adventure a) {
        super(a, new String[]{"RUN"});
    }

    @Override
    public String validateAndExecute(Player p, String[] args) {
        if (args.length == 1) {
            return "Run where?";
        } else if (args.length == 2) {
            return run(p, Util.consolidateArguments(args));
        } else {
            return "That is not a valid speedwalk!\nSyntax: run <directions>";
        }
    }

    private String run(Player p, String dirs) {
        ArrayList<Character> directions = new ArrayList<Character>();
        int timesToEnter = 1;
        boolean numeric = false;
        for (int c = 0; c < dirs.length(); c++) {
            if (numeric) {
                if (Util.isInteger(dirs.charAt(c) + "")) {
                    timesToEnter = Integer.parseInt(timesToEnter + "" + dirs.charAt(c));
                } else {
                    numeric = false;
                    c--;
                }
            } else {
                if (Util.isInteger(dirs.charAt(c) + "")) {
                    numeric = true;
                    timesToEnter = Integer.parseInt(dirs.charAt(c) + "");
                } else {
                    if (Util.isDirection(dirs.charAt(c) + "")) {
                        for (int d = 0; d < timesToEnter; d++) {
                            directions.add(dirs.charAt(c));
                        }
                        timesToEnter = 1;
                    } else {
                        return "One or more characters in that speedwalk are not valid directions!";
                    }
                }
            }
        }

        if (directions.size() > 0) {
            if (canMove(p, directions.get(0))) {
                String output = move(p, directions.get(0));
                for (int c = 1; c < directions.size(); c++) {
                    if (canMove(p, directions.get(c))) {
                        output += "\n" + move(p, directions.get(c));
                    } else {
                        return output + "\n" + move(p, directions.get(c));
                    }
                }
                return output;
            } else {
                return move(p, directions.get(0));
            }
        } else {
            return "That is not a valid speedwalk!";
        }
    }

    private String move(Player player, char dir) {
        int x = player.x();
        int y = player.y();
        int z = player.z();

        if (player.inCombat()) {
            return "You cannot do that in combat!";
        } else {
            if (!rooms.isBlocked(x, y, z, dir)) {
                if (rooms.isClosed(x, y, z, dir)) {
                    return "That direction is closed!";
                } else {
                    String direction = Util.fillDir(dir);
                    if (direction.equals("upper")) {
                        direction = "for above";
                    } else if (direction.equals("lower")) {
                        direction = "for below";
                    } else {
                        direction = "to the " + direction.substring(0, direction.length() - 3);
                    }
                    
                    out.broadcastLocalToPlayer(player,
                            ColourUtil.colourise(player.getName(), ColourUtil.magenta)
                            + " leaves " + direction + ".");

                    rooms.movePlayer(player, dir);

                    if (player.recordingSpeedwalk()) {
                        player.addToSpeedwalk(dir);
                    }

                    out.broadcastLocalToPlayer(player,
                            ColourUtil.colourise(player.getName(), ColourUtil.magenta)
                            + " enters the room.");

                    String output = adv.printRoom(player);
                    if (rooms.updatePlayerSpawn(player)) {
                        output += "\n\nYour respawn location has been "
                                + "updated to this location.";
                    }

                    String aggroOut = rooms.aggroMobsAttack(player);
                    if (aggroOut.length() > 0) {
                        output += "\n\n" + aggroOut;
                    }
                    return output;
                }
            } else {
                return "You cannot move any further in that direction!";
            }
        }
    }

    private boolean canMove(Player player, char dir) {
        int x = player.x();
        int y = player.y();
        int z = player.z();

        if (player.inCombat()) {
            return false;
        } else {
            if (!rooms.isBlocked(x, y, z, dir)) {
                if (rooms.isClosed(x, y, z, dir)) {
                    return false;
                } else {
                    return true;
                }
            } else {
                return false;
            }
        }
    }
}
